import { _decorator, Component, Node, Vec3, tween, v3, v2, Vec2 } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('BezierMovement')
export class BezierMovement extends Component {

    // 指定球体需要经过的路径点（世界坐标）
    @property([Vec3])
    public points: Vec3[] = [];

    // 移动速度（单位：秒）
    @property
    public moveSpeed: number = 5;

    // 曲线高度控制因子
    @property
    public curveHeight: number = 1.5;

    // 路径点的细分精度（点数量）
    @property
    public segmentation: number = 50;

    // 是否在开始时自动移动
    @property
    public playOnStart: boolean = true;

    // 存储计算出的完整贝塞尔路径点
    private _pathPoints: Vec3[] = [];

    start() {
        if (this.points.length < 2) {
            console.warn('Need at least 2 points to move');
            return;
        }

        // 生成完整的贝塞尔路径
        this.generateBezierPath();

        if (this.playOnStart) {
            this.startMovement();
        }
    }

    /**
     * 生成多段贝塞尔曲线连接的完整路径
     */
    generateBezierPath() {
        this._pathPoints = [];

        // 首先将第一个点加入路径
        this._pathPoints.push(this.points[0]);

        // 遍历点数组，每两个主控制点之间生成一段贝塞尔曲线
        for (let i = 0; i < this.points.length - 1; i++) {
            const startPoint = this.points[i];
            const endPoint = this.points[i + 1];

            // 获取控制点（这里使用两点中间上方某个点作为控制点来创造曲线）
            const controlPoint = this.calculateControlPoint(startPoint, endPoint);

            // 计算这段贝塞尔曲线上的细分点
            for (let j = 1; j <= this.segmentation; j++) {
                const t = j / this.segmentation;
                const point = this.calculateBezierPoint(startPoint, controlPoint, endPoint, t);
                this._pathPoints.push(point);
            }
        }
    }

    /**
     * 计算贝塞尔曲线的控制点（使用两点中间上方的点）
     */
    calculateControlPoint(startPoint: Vec3, endPoint: Vec3): Vec3 {
        // 计算中点
        const midX = (startPoint.x + endPoint.x) / 2;
        const midY = (startPoint.y + endPoint.y) / 2;
        const midZ = (startPoint.z + endPoint.z) / 2;

        // 计算两点间的距离
        const distance = Vec3.distance(startPoint, endPoint);

        // 在中点的基础上增加一些高度来形成曲线，高度受距离和curveHeight因子影响
        // 你可以根据需要调整这个计算方式
        const controlY = midY + distance * 0.3 * this.curveHeight; // 控制Y轴高度

        return v3(midX, controlY, midZ);
    }

    /**
     * 根据t参数计算二阶贝塞尔曲线上的点
     * @param p0 起点
     * @param p1 控制点
     * @param p2 终点
     * @param t 参数t [0, 1]
     */
    calculateBezierPoint(p0: Vec3, p1: Vec3, p2: Vec3, t: number): Vec3 {
        // 贝塞尔曲线公式：B(t) = (1-t)²P0 + 2(1-t)tP1 + t²P2
        const t1 = 1 - t;
        const x = t1 * t1 * p0.x + 2 * t1 * t * p1.x + t * t * p2.x;
        const y = t1 * t1 * p0.y + 2 * t1 * t * p1.y + t * t * p2.y;
        const z = t1 * t1 * p0.z + 2 * t1 * t * p1.z + t * t * p2.z;

        return v3(x, y, z);
    }

    /**
     * 开始移动
     */
    startMovement() {
        // 使用cc.tween沿着路径点移动
        const tw = tween(this.node);

        // 为路径中的每个点添加移动动作
        for (const point of this._pathPoints) {
            tw.to(this.moveSpeed / this._pathPoints.length, { position: point });
        }

        // 循环执行
        tw.call(() => {
            // 移动完成后的回调，可以在这里处理完成后逻辑，如循环移动等
            console.log('Movement completed!');
        }).start();
    }

    /**
     * 可视化路径（调试用，需要在场景中有一个LineRenderer组件或类似的可视化方法）
     */
    // debugDrawPath() {
    //     // 这里需要你根据使用的渲染方式绘制路径
    //     // 例如使用Graphics组件或者Cocos Creator的几何渲染器
    // }
}